package com.samp.solr.file2solr3;

import com.samp.solr.file2solr.ErrorIntentionExtract;
import org.apache.commons.lang3.StringUtils;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.params.CommonParams;

import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

/**
 * 生成精排所需要的训练数据。
 */
public class GenerateTrainingData {

    private static final String SOLR_FIELD_CONTENT = "content";
    private static final String SOLR_FIELD_INTENTION = "intention";
    private static final String SOLR_FIELD_CONTENT_FULL_MATCH = "contentFullMatch";
    //    private static final String BASE_SOLR_URL = "http://localhost:8080/solr/callcenter";
//    private static final String BASE_SOLR_URL = "http://localhost:8080/solr/gcc-omcp";
    private static final String BASE_SOLR_URL = "http://localhost:8080/solr/test";

    private static Map<String,Float> weightMap = new HashMap<>();

    private static final Float minScore = 4.0f; //最小分值
    private static final Float minRate = 1.2f; //最小比值

    static {
        initialWeightMap();
    }

    private static void generateData(String rawPath, String outFile,Integer topN) throws Exception{
        Path filePath = Paths.get(rawPath);
        BufferedReader bufferReader = Files.newBufferedReader(filePath, StandardCharsets.UTF_8);
        String line;
        try {
            List<String> resultList = new ArrayList<>();
            resultList.add("id\tqid1\tqid2\tquestion1\tquestion2\tis_duplicate");
            SolrClient solrClient =new HttpSolrClient.Builder(BASE_SOLR_URL).build();
            Integer index = 0;
            long allStart = System.currentTimeMillis();
            long start = System.currentTimeMillis();
            while( (line = bufferReader.readLine()) != null ){
                if( StringUtils.isBlank(line) ){
                    System.out.println("blank line,continue..");
                    continue;
                }
                String[] splits = line.split("\t");
                if( splits.length != 3 ){
                    System.out.println("error data:"+line);
                    continue;
                }
                String rawWord = splits[0];
                String rawIntention  = splits[1];
                String intention = extractIntentionWord(rawIntention);
                if( intention == null ){
                    continue;
                }
                int recordNeed = topN+1;
                List<WordIntention> solrResultList = getTopNIntentions(solrClient, rawWord, recordNeed);
                if( solrResultList.size() < recordNeed ){
                    recordNeed = solrResultList.size();
                }
                Set<String> removeDulSet = new HashSet<>();
                for(int i = 0 ; i < recordNeed-1; i++){
                    //如果满足直接返回的条件（分数大于4，且上条记录/当条记录>1.2），则过滤掉。
                    WordIntention wi = solrResultList.get(i);
                    WordIntention wiNext = solrResultList.get(i+1);
                    if( wi.getScore() > minScore && wi.getScore()/wiNext.getScore() > minRate ){
//                        System.out.println("return return.."+line);
                        continue;
                    }
                    Integer isMatch = 0;
                    if( wi.getIntention().equals(rawIntention) ){
                        isMatch = 1;
                    }
//                    resultList.add(getTrainningData(index,wi.getWord(), intention,isMatch)); wrong
//                    resultList.add(getTrainningData(index, rawWord ,wi.getWord() ,isMatch));  A - A1 type
                    String solrIntention = extractIntentionWord(wi.getIntention());
                    if( !removeDulSet.contains(solrIntention)) {
                        resultList.add(getTrainningData(index, rawWord, solrIntention, isMatch));  // A - B1 type
                        removeDulSet.add(solrIntention);
                        index++;
                    }
                    if( index % 5000 == 0 ){
                        System.out.println("processed 5000 lines, cost="+((System.currentTimeMillis()-start)*1.0/1000)+" 秒,index="+index);
                        start = System.currentTimeMillis();
                    }
                }
//                if( index > 100 ){
//                    break;
//                }
            }
//            for(String s:resultList){
//                System.out.println(s);
//            }
            ErrorIntentionExtract.saveResultToFile(resultList,outFile);
            System.out.println("save "+ resultList.size()+" lines, cost "+((System.currentTimeMillis()-allStart)*1.0/(1000*60))+" 分钟");
        }catch (IOException e) {
            e.printStackTrace();
        }finally{
            bufferReader.close();
        }
    }

    public static String getTrainningData(Integer index, String word, String intention, Integer isMatch){
        StringBuilder sb = new StringBuilder();
        sb.append(index).append("\t").append(index).append("\t").append(index).append("\t");
        sb.append(word).append("\t").append(intention).append("\t").append(isMatch);
        return sb.toString();
    }

    /**
     * 提取意图文字信息，用于训练
     * @param intention
     */
    public static String extractIntentionWord(String intention){
        String[] splits = intention.split("#");
        List<String> list = new ArrayList<>();
        for(String s :splits){
            String[] details = s.split("=");
            if( details.length != 2 ){
                return null;
            }
            if(  !"default".equals(details[1]) && !"execute".equals(details[1])
//                    && !"chat".equals(details[1]) && !"集外".equals(details[1])
            ){
                list.add(details[1]);
            }
        }
        return StringUtils.join(list," ");
    }


    public static List<WordIntention> getTopNIntentions(SolrClient solrClient, String word, Integer topN) throws Exception{
        SolrQuery query = new SolrQuery();
        query.set(CommonParams.QT, "/select");
        query.set(CommonParams.START, "0");
        query.set(CommonParams.ROWS, topN);
//        String queryParam = SOLR_FIELD_CONTENT+":"+addWeightToWord(word)+" OR "+ SOLR_FIELD_CONTENT_FULL_MATCH+":"+"\""+word+"\"^8";
        String queryParam = generateQueryParam(word);
        query.set(CommonParams.Q, queryParam);
        query.set(CommonParams.FL, SOLR_FIELD_CONTENT+","+SOLR_FIELD_INTENTION+",score");
        List<WordIntention> resultList = new ArrayList<>();
        QueryResponse response = solrClient.query(query);
        SolrDocumentList documentList = response.getResults();
        for( SolrDocument doc : documentList ) {
            WordIntention wi = new WordIntention();
            String docContent = (String) doc.getFieldValue(SOLR_FIELD_CONTENT);
            String docIntention = (String) doc.getFieldValue(SOLR_FIELD_INTENTION);
            Float docScore = (Float) doc.getFieldValue("score");
            wi.setWord(docContent);
            wi.setIntention(docIntention);
            wi.setScore(docScore);
            resultList.add(wi);
        }
        return resultList;
    }

    public static String generateQueryParam(String word){
        return SOLR_FIELD_CONTENT+":"+addWeightToWord(word)+" OR "+ SOLR_FIELD_CONTENT_FULL_MATCH+":"+"\""+word+"\"^8";
    }

    private static String addWeightToWord(String word){
        if( StringUtils.isBlank(word) ){
            return word;
        }
        String[] wordSplits = word.split(" ");
        String[] weightWord = new String[wordSplits.length];
        for(int i = 0 ;i < wordSplits.length ; i++ ){
            if( weightMap.containsKey(wordSplits[i]) ){
                weightWord[i]=wordSplits[i]+"^"+String.valueOf(weightMap.get(wordSplits[i]));
            }else {
                weightWord[i]=wordSplits[i];
            }
        }
        return StringUtils.join(weightWord, " ");
    }

    private static void initialWeightMap(){
        System.out.println("start initial weight map...");
        String rawPath = "D:\\gcc-omcp\\new\\nlp\\customerweight.txt";
        Path filePath = Paths.get(rawPath);
        BufferedReader bufferReader = null;
        try {
            bufferReader = Files.newBufferedReader(filePath, StandardCharsets.UTF_8);
            String line;
            while ((line = bufferReader.readLine()) != null) {
                if( StringUtils.isNotBlank(line) ){
                    //如果注释掉，直接continue.
                    String data = line.trim();
                    if( data.startsWith("#") ){
                        continue;
                    }
                    String[] splits = data.split(",");
                    if( splits.length >= 2 ){
                        try {
                            for( int i = 1 ; i< splits.length ; i++ ){
                                weightMap.put(splits[i].trim(), Float.valueOf(splits[0]));
                            }
                        }catch (Exception e1){
                            e1.printStackTrace();
                        }
                    }else {
                        System.out.println("error line:"+line);
                    }
                }
            }
            System.out.println("加载关键字权重个数："+weightMap.size());
        }catch (IOException e) {
            e.printStackTrace();
        }finally{
            if( bufferReader != null ) {
                try {
                    bufferReader.close();
                }catch (Exception e1){
                    e1.printStackTrace();
                }
            }
        }

    }

    public static void main(String[] args) {
//        String a = "action.name=查询#target.name=理赔#target.params1=进度";
//        System.out.println(extractIntentionWord(a));
        String rawPath = "D:\\gcc-omcp\\new\\data\\027_total_words.txt";
        String outPath = "D:\\gcc-omcp\\trainning\\95511_training_08.txt";
        Integer topN = 5;
        try {
            generateData(rawPath, outPath, topN);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}

class WordIntention{
    private String word;
    private String intention;
    private Float score;

    public WordIntention(){

    }

    public WordIntention(String word, String intention){
        this.word = word;
        this.intention = intention;
    }

    public Float getScore() {
        return score;
    }

    public void setScore(Float score) {
        this.score = score;
    }

    public String getWord() {
        return word;
    }

    public void setWord(String word) {
        this.word = word;
    }

    public String getIntention() {
        return intention;
    }

    public void setIntention(String intention) {
        this.intention = intention;
    }

    @Override
    public String toString() {
        return  word + "\t" + intention;
    }
}